---
title: Componentes
description: Uma introdução à sintaxe de componentes .astro.
i18nReady: true
---

**Componentes Astro** são parte fundamental de qualquer projeto Astro. São componentes de template com apenas HTML e sem execução no lado do cliente. Você pode localizar um componente Astro por sua extensão de arquivo: `.astro`.

Componentes Astro são extremamente flexíveis. Geralmente, um componente Astro irá conter alguma **UI reutilizável na página**, como um cabeçalho ou um cartão de perfil. Outras vezes, um componente Astro pode conter um pequeno pedaço de HTML, como uma coleção de tags `<meta>` comuns que facilitam trabalhar com SEO. Componentes Astro também pode conter o layout inteiro de uma página.

A coisa mais importante de entender sobre componentes Astro é que eles **não renderizam no lado do cliente**. Eles renderizam para HTML tanto na hora da build ou sob demanda usando [renderização no lado do servidor (SSR)](/pt-br/guides/server-side-rendering/). Você pode incluir código JavaScript dentro do frontmatter do seu componente, e todo ele vai ser removido da página final enviada para o navegador dos seus usuários. O resultado é um site mais rápido, com nenhum JavaScript por padrão.

Quando seu componente Astro realmente precisar de interatividade no lado do cliente, você pode adicionar [tags `<script>` tradicionais do HTML](/pt-br/guides/client-side-scripts/) ou [componentes de um Framework de UI](/pt-br/guides/framework-components/#hidratando-componentes-interativos).


## Estrutura do Componente

Um componente Astro é feito de duas partes principais: o **Script do Componente** e o **Template do Componente**. Cada parte executa um trabalho diferente, porém juntos eles providenciam um framework que é ao mesmo tempo fácil de utilizar e expressivo o suficiente para lidar com qualquer que seja o que você deseja construir.

```astro title="src/components/ComponenteVazio.astro"
---
// Script do Componente (JavaScript)
---
<!-- Template do Componente (HTML + Expressões do JS) -->
```

### O Script do Componente

Astro utiliza uma cerca de código (`---`) para identificar o script do seu componente Astro. Se você já escreveu Markdown antes, você já deve estar familiar com um conceito similar chamado de *frontmatter*. A ideia do Astro de um script do componente foi diretamente inspirado por este conceito.

Você pode utilizar o script do componente para escrever qualquer código JavaScript necessário para renderizar o seu template. Isso pode incluir:

- importar outros componentes Astro
- importar componentes de outros frameworks, como React
- importar dados, como um arquivo JSON
- buscar conteúdo de uma API ou banco de dados
- criar variáveis que você vai referenciar no seu template


```astro title="src/components/MeuComponente.astro"
---
import UmComponenteAstro from '../components/UmComponenteAstro.astro';
import UmComponenteReact from '../components/UmComponenteReact.jsx';
import algunsDados from '../dados/pokemon.json';

// Acesse props passadas ao componente, como `<X titulo="Olá, Mundo!" />`
const { titulo } = Astro.props;
// Busque dados externos, até mesmo de uma API privada ou banco de dados
const dados = await fetch('ALGUMA_URL_SECRETA_API/usuarios').then(r => r.json());
---
<!-- Seu template está aqui! -->
```

A cerca de código é projetada para garantir que o JavaScript que você escreve nela está "cercado". Ele não irá escapar para a sua aplicação frontend ou cair na mão dos seus usuários. Você pode com segurança escrever aqui código que é custoso ou sensível (como uma chamada ao seu banco de dados privado) sem se preocupar com ele cair no navegador do seu usuário.

:::tip
Você pode até mesmo escrever TypeScript no script do componente!
:::

### O Template do Componente

O template do componente está abaixo da cerca do código e determina o HTML que irá sair do seu componente.

Se você escrever puro HTML aqui, o seu componente irá renderizar esse HTML em qualquer página Astro em que é importado e utilizado.

Porém, a [sintaxe do template do script do Astro](/pt-br/basics/astro-syntax/) também suporta **expressões JavaScript**, tags [`<style>`](/pt-br/guides/styling/#estilização-em-astro) e [`<script>`](/pt-br/guides/client-side-scripts/#utilizando-script-no-astro) do Astro, **componentes importados**, e [**diretivas especiais do Astro**](/pt-br/reference/directives-reference/). Dados e valores definidos no script do componente podem ser utilizados no template do componente para produzir HTML criado dinamicamente.

```astro title="src/components/MeuPokemonFavorito.astro"
---
// O script do seu componente está aqui!
import Banner from '../components/Banner.astro';
import ComponentePokemonReact from '../components/ComponentePokemonReact.jsx';
const meuPokemonFavorito = [/* ... */];
const { titulo } = Astro.props;
---
<!-- comentários HTML são suportados! -->
{/* sintaxe de comentário do JS também é válida! */}

<Banner />
<h1>Olá, mundo!</h1>

<!-- Use props e outras variáveis do script do componente: -->
<p>{titulo}</p>

<!-- Inclua outros componentes de frameworks de UI com a diretiva `client:` para hidratá-los: -->
<ComponentePokemonReact client:visible />

<!-- Misture HTML com expressões JavaScript, similar ao JSX: -->
<ul>
  {meuPokemonFavorito.map((dados) => <li>{dados.nome}</li>)}
</ul>

<!-- Use uma diretiva de template para construir nomes de classe a partir de múltiplas strings ou até mesmo objetos! -->
<p class:list={["adicione", "dinâmicos", {classNames: true}] />
```

## Design baseado em componente

Componentes são projetados para serem **reusáveis** e **combináveis**. Você pode utilizar componentes dentro de outros componentes, criando UIs cada vez mais avançadas. Por exemplo, um componente `Botao` pode ser utilizado para criar um componente `GrupoBotoes` assim:

```astro title="src/components/GrupoBotoes.astro"
---
import Botao from './Botao.astro';
---
<div>
  <Botao titulo="Botão 1" />
  <Botao titulo="Botão 2" />
  <Botao titulo="Botão 3" />
</div>
```


## Props do Componente

Um componente Astro pode definir e aceitar props. Essas props então se tornam disponíveis ao template do componente para renderizar HTML. Props estão disponíveis na global `Astro.props` no script do frontmatter.

Aqui está um exemplo de um componente que recebe uma prop `saudacao` e uma prop `nome`. Note que as props a serem recebidas são desconstruídas a partir do objeto global `Astro.props`.

```astro "Astro.props"
---
// src/components/TituloSaudacao.astro
// Uso: <TituloSaudacao saudacao="Salve" nome="Parceiro" />
const { saudacao, nome } = Astro.props;
---
<h2>{saudacao}, {nome}!</h2>
```

Este componente, quando importado e renderizado em outros componentes Astro, layouts ou páginas, pode passar essas props como atributos:

```astro /(\w+)=\S+/
---
// src/components/CartaoSaudacoes.astro
import TituloSaudacao from './TituloSaudacao.astro';
const nome = 'Astro';
---
<h1>Cartão de Saudações</h1>
<TituloSaudacao saudacao="Oi" nome={nome} />
<p>Espero que você tenha um dia maravilhoso!</p>
```

Você também pode definir suas props com TypeScript, exportando uma interface de tipo `Props`. Astro vai automaticamente pegar qualquer interface `Props` exportada e dar avisos/erros de tipagem para o seu projeto. Estas props também podem dar valores padrão quando desconstruídas de `Astro.props`.

```astro ins={3-6}
---
// src/components/TituloSaudacao.astro
export interface Props {
  nome: string;
  saudacao?: string;
}

const { saudacao = "Olá", nome } = Astro.props;
---
<h2>{saudacao}, {nome}!</h2>
```

Props do componente podem receber valores padrões para serem utilizados quando nenhum é providenciado.

```astro ins="= \"Olá\"" ins="= \"Astronauta\""
---
// src/components/TituloSaudacao.astro
const { saudacao = "Olá", nome = "Astronauta" } = Astro.props;
---
<p>{saudacao}, {nome}!</p>
```

## Slots

O elemento `<slot />` é um placeholder para conteúdo HTML externo, permitindo que você injete elementos-filho de outros arquivos no template do seu componente.

Por padrão, todos os elementos-filho passados para o componente serão renderizados em seu `<slot />`.

:::note
Diferente de _props_, que são atributos passados para um componente Astro, disponível para uso dentro de si com `Astro.props()`, _slots_ renderizam elementos HTML filho aonde eles estão escritos.
:::

```astro "<slot />"
---
// src/components/Involucro.astro
import Cabecalho from './Cabecalho.astro';
import Logo from './Logo.astro';
import Rodape from './Rodape.astro';

const { titulo } = Astro.props;
---
<div id="invólucro-do-conteúdo">
  <Cabecalho />
  <Logo />
  <h1>{titulo}</h1>
  <slot />  <!-- filhos irão para cá -->
  <Rodape />
</div>
```

```astro {6-7}
---
// src/pages/fred.astro
import Involucro from '../components/Involucro.astro';
---
<Involucro titulo="Página do Fred">
  <h2>Tudo sobre Fred</h2>
  <p>Aqui estão algumas coisas sobre Fred.</p>
</Involucro>
```

Este padrão é a base de um [componente de layout Astro](/pt-br/basics/layouts/): uma página inteira de conteúdo HTML pode ser "envolta" com tags `<AlgumComponenteDeLayout></AlgumComponenteDeLayout>` e enviadas até o componente para ser renderizada dentro de elementos comuns da página definidos lá.



### Slots Nomeados

Um componente Astro também pode ter slots nomeados. Isto permite que você passe apenas elementos HTML com o nome de slot correspondente até a localização do slot.

Slots são nomeados usando o atributo `name`:

```astro /<slot .*?/>/
---
// src/components/Involucro.astro
import Cabecalho from './Cabecalho.astro';
import Logo from './Logo.astro';
import Rodape from './Rodape.astro';

const { titulo } = Astro.props;
---
<div id="invólucro-do-conteúdo">
  <Cabecalho />
  <slot name="depois-do-cabecalho"/>  <!--  filhos com o atributo `slot="depois-do-cabecalho"` irão para cá -->
  <Logo />
  <h1>{titulo}</h1>
  <slot />  <!--  filhos sem um atributo `slot`, ou com `slot="default"` irão para cá -->
  <Rodape />
  <slot name="depois-do-rodape"/>  <!--  filhos com o atributo `slot="depois-do-rodape"` irão para cá -->
</div>
```

Para injetar conteúdo HTML dentro de um slot em particular, use o atributo `slot` em qualquer elemento filho para especificar o nome do slot. Todos os outros elementos filhos do componentes serão injetados no `<slot />` padrão (não nomeado).


```astro /slot=".*?"/
---
// src/pages/fred.astro
import Involucro from '../components/Involucro.astro';
---
<Involucro title="Página do Fred">
  <img src="https://minha.foto/fred.jpg" slot="depois-do-cabecalho">
  <h2>Tudo sobre Fred</h2>
  <p>Aqui estão algumas coisas sobre Fred.</p>
  <p slot="depois-do-rodape">Copyright 2022</p>
</Involucro>
```

:::tip
Use um atributo `slot="meu-slot"` no elemento filho que você quer passar através de um correspondente placeholder `<slot name="meu-slot"/>` no seu componente.
:::

Para passar múltiplos elementos HTML para um placeholder `<slot/>` de um componente sem ter uma `<div>` envolta, use o atributo `slot=""` no [Componente `<Fragment/>` do Astro](/pt-br/reference/api-reference/#fragment-):

```astro title="src/components/TabelaCustomizada.astro" "<slot name="cabecalho"/>" "<slot name="corpo"/>"
---
// Cria uma tabela customizada com slots nomeados para o conteúdo do cabeçalho e do corpo
---
<table class="bg-white">
  <thead class="sticky top-0 bg-white"><slot name="cabecalho"/></thead>
  <tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="corpo"/></tbody>
</table>
```

Injete múltiplas linhas e colunas de conteúdo HTML usando o atributo `slot=""` para especificar o conteúdo do `"cabecalho"` e `"corpo"`. Elementos inviduais do HTML também podem ser estilizados:

```astro title="src/components/TabelaDeEstoque.astro" {5-7, 9-13} '<Fragment slot="cabecalho">' '<Fragment slot="corpo">'
---
import TabelaCustomizada from './TabelaCustomizada.astro';
---
<TabelaCustomizada>
  <Fragment slot="cabecalho"> <!-- passar cabeçalho da tabela -->
    <tr><th>Nome do Produto</th><th>Quantidade no estoque</th></tr>
  </Fragment>
  <Fragment slot="corpo"> <!-- passar corpo da tabela -->
    <tr><td>Chinelos</td><td>64</td></tr>
    <tr><td>Botas</td><td>32</td></tr>
    <tr><td>Tênis</td><td class="text-red-500">0</td></tr>
  </Fragment>
</TabelaCustomizada>
```

Note que slots nomeados precisam ser um filho imediato de um componente. Você não pode passar slots nomeados através de elementos aninhados.

:::tip
Slots nomeados também podem ser passados para [componentes de frameworks de UI](/pt-br/guides/framework-components/)!
:::

:::note
Não é possível gerar dinamicamente um slot nomeado no Astro, como por exemplo dentro de uma função map. Se essa funcionalidade é necessária dentro de um componente de um framework de UI, o melhor é gerar esses slots dinâmicos dentro do próprio framework.
:::


### Conteúdo de Fallback para Slots
Slots também podem renderizar **conteúdo de fallback**. Quando não tem filhos correspondentes passados a um slot, um elemento `<slot />` irá renderizar o seu próprio filho placeholder.

```astro {14}
---
// src/components/Involucro.astro
import Cabecalho from './Cabecalho.astro';
import Logo from './Logo.astro';
import Rodape from './Rodape.astro';

const { titulo } = Astro.props;
---
<div id="invólucro-do-conteúdo">
  <Cabecalho />
  <Logo />
  <h1>{titulo}</h1>
  <slot>
    <p>Esse é o meu conteúdo de fallback se nenhum filho for passado ao slot</p>
  </slot>
  <Rodape />
</div>
```

### Transferindo slots

Slots podem ser transferidos para outros componentes. Por exemplo, quando criando layouts aninhados:

```astro title="src/layouts/BaseLayout.astro" {9,12}
---
---

<html lang="pt-BR">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
    <slot name="cabecalho"/>
	</head>
	<body>
		<slot />
	</body>
</html>
```

```astro {6,7}
// src/layouts/LayoutInicio.astro
---
import LayoutBase from './LayoutBase.astro';
---

<LayoutBase>
  <slot name="cabecalho" slot="cabecalho"/>
  <slot />
</LayoutBase>
```

:::note
Slots nomeados podem ser transferidos para outro componente usando ambos os atributos `name` e `slot` em uma tag `<slot />`
:::

Agora, os slots padrão e `cabecalho` passados para `LayoutInicio` vão ser transferidos para o pai `LayoutBase`

```astro
// src/pages/index.astro
---
import LayoutInicio from '../layouts/LayoutInicio.astro';
---

<LayoutInicio>
	<title slot="cabecalho">Astro</title>
	<h1>Astro</h1>
</LayoutInicio>
```


## Componentes HTML

Astro suporta a importação e uso de arquivos `.html` como componentes ou como arquivos no subdiretório `src/pages/` como páginas. Você pode querer utilizar componentes HTML se você estiver reutilizando código de um site já construído sem um framework ou se você quer se certificar de que seu componente não tem funcionalidades dinâmicas.

Componentes HTML devem conter apenas HTML válido, logo não tem as funcionalidades principais de componentes Astro:
- Eles não suportam frontmatter, importações no lado do servidor ou expressões dinâmicas.
- Quaisquer tags `<script>` ficam sem bundle, sendo tratadas como se tivessem `is:inline`. 
- Eles podem apenas [referenciar assets que estão no diretório `public/`](/pt-br/basics/project-structure/#public).

:::note
Um [elemento `<slot />`](/pt-br/basics/astro-components/#slots) dentro de um componente HTML irá funcionar assim como funcionaria em um componente Astro. Para utilizar o [Componente Web HTML Slot](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) no lugar, adicione `is:inline` ao seu elemento `<slot>`.
:::

## Próximos Passos

import ReadMore from '~/components/ReadMore.astro';

<ReadMore>Aprenda sobre como utilizar [componentes de frameworks JavaScript](/pt-br/guides/framework-components/) em seu projeto Astro.</ReadMore>
